package com.starblink.imgsearch.camera.ui

import android.annotation.SuppressLint
import android.app.Dialog
import android.content.ActivityNotFoundException
import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageButton
import android.widget.ImageView
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.camera.view.PreviewView
import com.alibaba.android.arouter.facade.annotation.Route
import com.blankj.utilcode.util.PermissionUtils
import com.bumptech.glide.Glide
import com.bumptech.glide.Priority
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.CustomViewTarget
import com.bumptech.glide.request.target.Target
import com.bumptech.glide.request.transition.Transition
import com.google.android.material.tabs.TabLayout
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.permissions.PermissionConfig
import com.skydoves.balloon.ArrowOrientation
import com.skydoves.balloon.ArrowPositionRules
import com.skydoves.balloon.Balloon
import com.starblink.android.basic.base.activity.BaseTVMActivity
import com.starblink.android.basic.ext.bindFragment
import com.starblink.android.basic.ext.click
import com.starblink.android.basic.ext.commContext
import com.starblink.android.basic.ext.createCameraAccessDialog
import com.starblink.android.basic.ext.enableCorner
import com.starblink.android.basic.ext.gone
import com.starblink.android.basic.ext.invisible
import com.starblink.android.basic.ext.toast
import com.starblink.android.basic.ext.visible
import com.starblink.android.basic.extension.dp2px
import com.starblink.android.basic.extension.navigationTo
import com.starblink.android.basic.guide.SkNoviceManage
import com.starblink.android.basic.guide.bean.SkGuideEnum
import com.starblink.android.basic.sensorsdata.exposure.isInScreen
import com.starblink.android.basic.sensorsdata.extension.trackData
import com.starblink.android.basic.sensorsdata.room.entity.SkAntEntity
import com.starblink.android.basic.sensorsdata.spm.GTrackerAssistUtils
import com.starblink.android.basic.sensorsdata.spm.cfg.SpmElementDef
import com.starblink.android.basic.sensorsdata.spm.cfg.SpmPageDef
import com.starblink.android.basic.sensorsdata.spm.impl.SpmTrackHandler
import com.starblink.android.basic.util.CoroutineUpdateTask
import com.starblink.android.basic.util.FlowCountDownTimer
import com.starblink.android.basic.util.bus.FlowBus
import com.starblink.android.basic.util.bus.FlowConst
import com.starblink.basic.ext.nowTime
import com.starblink.basic.log.SKLogger
import com.starblink.basic.route.RoutePage
import com.starblink.basic.style.R
import com.starblink.basic.util.AlbumUtils
import com.starblink.imgsearch.barcode.ui.BarCodeFragment
import com.starblink.imgsearch.camera.BlurBitmap
import com.starblink.imgsearch.camera.CamConfig
import com.starblink.imgsearch.camera.CameraMode
import com.starblink.imgsearch.camera.ImageCapturer
import com.starblink.imgsearch.camera.TabViewHolder
import com.starblink.imgsearch.databinding.ActivityCameraBinding
import com.starblink.imgsearch.imgrecognition.ui.ImgRecognitionFragment
import com.starblink.library.widget.databinding.LayoutBallonCameraAlbumFirstBinding
import com.starblink.library.widget.novice_guide.camera.ImgSearchPopView
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch

@Route(path = RoutePage.ImageSearch.PAGE_CAMERA)
class CameraTVMActivity : BaseTVMActivity<ActivityCameraBinding, CameraVM>() {
    companion object {
        const val TAG = "Camera"
        const val TAB_ITEM_CAMERA = 0 // 默认TAB-Camera
        const val TAB_ITEM_SCAN = 1 // TAB-Scan
    }

    override fun initViewBinding(): ActivityCameraBinding =
        ActivityCameraBinding.inflate(layoutInflater)

    override fun isStatusBarLightMode() = false

    private var fromOnCreate = true

    override fun onCreate(savedInstanceState: Bundle?) {
//        BarUtils.transparentNavBar(this)
        super.onCreate(savedInstanceState)
        SKLogger.e(TAG, "onCreate")
        fromOnCreate = true

        // 保证页面只曝光一次
        if (!viewModel.pageExposure) {
            pageExposure(SpmPageDef.CameraRoute)
            viewModel.pageExposure = true
        }

        // 设置底部状态栏颜色
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            window.navigationBarColor = Color.parseColor("#000000")
        }

//        viewBinding.btmStatusBar.updateLayoutParams<ConstraintLayout.LayoutParams> {
//            this.bottomMargin = CommUtils.getBottomStatusHeight()
//        }

//        viewBinding.btmStatusBar.height(CommUtils.getBottomStatusHeight())

        viewBinding.vBackIcon.click {
            finish()
            dismissBalloon()
        }

        initCameraRevelant()

        initTabAndViewPager()

        registerSystemAlbum()

        handleClick()

        // 在onResume中，检查权限，防止用户将App切换到后台后，将权限关闭
        checkPermissionsOnCreate()
    }

    override fun onStart() {
        super.onStart()
        SKLogger.e(TAG, "onStart")
    }

    override fun onResume() {
        super.onResume()
        SKLogger.e(TAG, "onResume")
        if (!fromOnCreate) {
            checkPermissionsOnResume()

            // 如果是结果页关闭
            // 显示隐藏的返回按钮
            viewBinding.vBackIcon.visible()
            // 隐藏毛玻璃背景
            mainOverlay.visibility = View.INVISIBLE
        }
        fromOnCreate = false
    }

    override fun onPause() {
        super.onPause()
        SKLogger.e(TAG, "onPause")
    }

    override fun onStop() {
        SKLogger.e(TAG, "onStop")
        super.onStop()
        lastFrame = null
    }

    override fun onDestroy() {
        SKLogger.e(TAG, "onDestroy")
        camConfig.cameraExecutor?.shutdownNow()
        downTimer.cancel()
        super.onDestroy()
    }

    // <editor-fold desc="权限相关">
    // 相机权限弹窗
    private var cameraAccessDialog: Dialog? = null

    /**
     * 检查拍照+图片文件读取权限
     * 如果有权限，初始化相机
     * 如果没有权限，申请权限
     */
    private fun checkPermissionsOnCreate() {
        SKLogger.i(TAG, "检查权限")
        imgRecognitionFrg.startTimerHideTop()
        var permissions = PermissionConfig.CAMERA + PermissionConfig.getReadPermissionArray(
            commContext(),
            SelectMimeType.ofImage()
        )
        if (PermissionUtils.isGranted(*permissions)) {
            SKLogger.i(TAG, "权限已授权")
            // 如果弹窗正在显示，关闭弹窗
            if (cameraAccessDialog != null
                && cameraAccessDialog!!.isShowing
            ) {
                cameraAccessDialog!!.cancel()
            }

            // 初始化相机
            camConfig.initializeCamera(true)
            showFirstAlbum()
            handleGuidePop()
        } else {
            SKLogger.i(TAG, "权限未授权，请求授权")
            PermissionUtils.permission(*permissions)
                .callback { isAllGranted, granted, _, _ ->
                    if (isAllGranted) {
                        SKLogger.i(TAG, "权限已授权")
                        camConfig.initializeCamera(true)
                        showFirstAlbum()
                        handleGuidePop()
                    } else {
                        SKLogger.i(TAG, "权限授权被拒绝，显示弹窗")
                        if (cameraAccessDialog == null
                            || !cameraAccessDialog!!.isShowing
                        ) {
                            if (cameraAccessDialog == null) {
                                cameraAccessDialog = createCameraAccessDialog()
                            }
                            cameraAccessDialog!!.show()
                        }
                    }
                }.request()
        }
    }

    private fun checkPermissionsOnResume() {
        if (PermissionUtils.isGranted(*PermissionConfig.CAMERA)) {
            // 初始化相机
            camConfig.initializeCamera(true)
        }
    }

    private fun showFirstAlbum() {
//        var img1 = Album2Utils.getLatestPhoto(mContext)
//
//        if (!img1?.second.isNullOrEmpty()&&img1?.first!=null) {
//            val currentTime =
//                System.currentTimeMillis() / 1000
//            if (currentTime - img1[0].mTime <= Album2Utils.SCREEN_SHOT_OFFSET_TIME_S) {
//                handleAlbumBalloon(viewBinding.btnGallery, img1[0].imgUrl)
//            }
//        }


//        handleAlbumBalloon(viewBinding.btnGallery, "/storage/emulated/0/DCIM/Screenshots/Screenshot_20230616-175549_Guang.jpg")
//        return
        var img1 = AlbumUtils.getLatestMediaPhoto(mContext)
        if (!img1?.second.isNullOrEmpty() && img1?.first != null) {
//            val currentTime =
//                System.currentTimeMillis() / 1000
//            if (currentTime - img1.first!! <= Album2Utils.SCREEN_SHOT_OFFSET_TIME_S) {
            handleAlbumBalloon(viewBinding.btnGallery, img1.second!!)

//            }
        }
    }
    // </editor-fold>

    // <editor-fold desc="TabAndViewPager">
    private val pageTitle = mutableListOf(
        "Camera",
        "Scan"
    )
    private val imgRecognitionFrg = ImgRecognitionFragment.obtainFragment()
    private val barCodeFragment = BarCodeFragment.obtainFragment()

    private fun initTabAndViewPager() {
        viewBinding.viewPager.bindFragment(
            supportFragmentManager,
            pageTitles = pageTitle,
            count = pageTitle.size
        )
        {
            when (it) {
                TAB_ITEM_CAMERA -> imgRecognitionFrg
                else -> barCodeFragment
            }
        }
        viewBinding.viewPager.offscreenPageLimit = pageTitle.size
        viewBinding.tabLayout.setupWithViewPager(viewBinding.viewPager)
        //处理tabLayout
        for (i in 0 until viewBinding.tabLayout.tabCount) {
            val tab = viewBinding.tabLayout.getTabAt(i)
            //给tab设置自定义布局
            tab!!.setCustomView(com.starblink.imgsearch.R.layout.img_search_tab_item)
            var tabVH = TabViewHolder(tab.customView!!)
            //填充数据
            tabVH.tvName.text = pageTitle[i]
            //默认选择第一项
            if (i == 0) {
                tabVH.setTabSelectedStyle()
            }
        }
        viewBinding.tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
            override fun onTabSelected(tab: TabLayout.Tab) {
                if (viewBinding.tabLayout.selectedTabPosition == TAB_ITEM_CAMERA) {
                    viewBinding.btnCapture.visible()
                    camConfig.switchMode(CameraMode.CAMERA)
                    SpmTrackHandler.addSingleTrackData(
                        SkAntEntity(
                            spmCnt = GTrackerAssistUtils.fetchElementValue(
                                SpmPageDef.CameraRoute, SpmElementDef.CameraTab
                            ),
                            params = mapOf("name" to pageTitle[0])
                        )
                    )
                } else {
                    viewBinding.btnCapture.invisible()
                    camConfig.switchMode(CameraMode.QR_SCAN)
                    barCodeFragment.starAnim()
                    dismissBalloon()
                    SpmTrackHandler.addSingleTrackData(
                        SkAntEntity(
                            spmCnt = GTrackerAssistUtils.fetchElementValue(
                                SpmPageDef.CameraRoute, SpmElementDef.CameraTab
                            ),
                            params = mapOf("name" to pageTitle[1])
                        )
                    )
                }

            }

            override fun onTabUnselected(tab: TabLayout.Tab) {
            }

            override fun onTabReselected(tab: TabLayout.Tab) {}
        })

        //默认选中第一个
        viewBinding.tabLayout.getTabAt(0)?.select()
    }
    // </editor-fold>

    // <editor-fold desc="相机相关">
    /**相机设置管理器*/
    lateinit var camConfig: CamConfig

    /**相机拍照管理器*/
    lateinit var imageCapturer: ImageCapturer

    /**相机预览View*/
    lateinit var previewView: PreviewView

    /**主浮层，Tab切换时显示毛玻璃图*/
    lateinit var mainOverlay: ImageView

    /**中间按钮：拍照*/
    lateinit var captureButton: ImageButton

    /**预览最近的一帧*/
    private var lastFrame: Bitmap? = null

    /**初始化相机相关内容*/
    private fun initCameraRevelant() {
        camConfig = CamConfig(this)
        imageCapturer = ImageCapturer(this)
        previewView = viewBinding.viewFinder
        mainOverlay = viewBinding.mainOverlay
        captureButton = viewBinding.btnCapture

        // 监听预览状态
        previewView.previewStreamState.observe(this) { state: PreviewView.StreamState ->
            if (state == PreviewView.StreamState.STREAMING) {
                // 预览View状态变为[预览中STREAMING]
                mainOverlay.visibility = View.INVISIBLE
            } else {
                // 预览View状态变为[空闲IDLE]
                showBlurLastFrame()
            }
        }
    }

    private fun showBlurLastFrame() {
        if (lastFrame != null) {
            // 主浮层显示最后一帧的毛玻璃效果图
            mainOverlay.setImageBitmap(BlurBitmap.blur(lastFrame!!))
            mainOverlay.visibility = View.VISIBLE
        }
    }

    /**条形码扫描成功回调*/
    fun onBarcodeScanResultSuccess(rawText: String) {
        SKLogger.e(TAG, "条形码=${rawText}")

        MainScope().launch {
            // 因为结果页顶部透明，所以相机页面需要显示Blur效果，隐藏返回按钮
            updateLastFrame()
            showBlurLastFrame()
            viewBinding.vBackIcon.gone()

            // 跳转结果页
            navigationTo(
                RoutePage.ImageSearch.PAGE_BARCODE_RESULT
            ) {
                withString(RoutePage.ImageSearch.ARGS_PRODUCT_BARCODE, rawText)
            }

            // 解绑相机
            camConfig.cameraProvider?.unbindAll()
        }
    }

    fun updateLastFrame() {
        lastFrame = previewView.bitmap
    }

    // </editor-fold>

    /**点击事件*/
    private fun handleClick() {
        viewBinding.btnCapture.click {
            imageCapturer.takePicture()
            dismissBalloon()
        }
        viewBinding.btnGallery.click {
            openSystemAlbum()
            dismissBalloon()
        }

        viewBinding.btnWitch.click {
            camConfig.toggleCameraSelector()
            dismissBalloon()
        }

        viewBinding.btnCapture.trackData(
            element = SpmElementDef.CameraButtonClick,
            page = SpmPageDef.CameraRoute,
            onlyHit = true,
        )
        viewBinding.btnGallery.trackData(
            element = SpmElementDef.CameraAlbum,
            page = SpmPageDef.CameraRoute,
            onlyHit = true,
        )
        viewBinding.btnWitch.trackData(
            element = SpmElementDef.CameraTurnLens,
            page = SpmPageDef.CameraRoute,
            onlyHit = true,
        )
    }

    // <editor-fold desc="系统相册">
    private var launcherSystemAlbum: ActivityResultLauncher<PickVisualMediaRequest>? = null

    /**注册系统相册*/
    private fun registerSystemAlbum() {
        // 多选 ActivityResultContracts.PickMultipleVisualMedia(maxItems = 1)
        launcherSystemAlbum = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) {
            SKLogger.d(CameraTVMActivity.TAG, "album select $it")
            it?.apply {
                imageCapturer.now = nowTime()
                imageCapturer.compressAndToResult(this)
            }
        }
    }

    /**打开系统相册*/
    private fun openSystemAlbum() {
        try {
            launcherSystemAlbum?.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
        } catch (e: ActivityNotFoundException) {
            toast("Can't find system album")
        }
        // Launching the photo picker (photos only)
//        pickMultipleVisualMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageOnly))
//// Launching the photo picker (video only)
//        pickMultipleVisualMedia.launch(PickVisualMediaRequest(PickVisualMedia.VideoOnly))
//// Launching the photo picker (GIF only)
//        pickMultipleVisualMedia.launch(PickVisualMediaRequest(PickVisualMedia.SingleMimeType("image/gif")))
    }
    // </editor-fold>

    private fun handleGuidePop() {
        viewBinding.vBackIcon.post {
            SkNoviceManage.whetherGuideCanBeDisplayed(
                sceneEnum = SkGuideEnum.IMG_SEARCH_GUIDE_1_13,
                //弹出即将状态置为false
                oncePopSetFalse = true,
                canPop = {
                    ImgSearchPopView.pushPopWindow(
                        mActivity,
                        viewBinding.vBackIcon,
                        viewBinding.root,
                        dismissCallBack = {
                        }
                    )
                }, hasPop = {
                }
            )
        }

    }


    private val downTimer = FlowCountDownTimer(time = 5)
    private var balloon: Balloon? = null
    private var task: CoroutineUpdateTask? = null
    private fun handleAlbumBalloon(view: View, imgUrl: String) {
        FlowBus.with<Boolean>(FlowConst.ALBUM_FIRST_POP_DISMISS).register(this) {
            balloon?.dismiss()
        }
        if (task == null) {
            task = CoroutineUpdateTask()
            task?.scheduleUpdate(500, action = {
                if (view.isInScreen()) {
                    task?.cancel()
                    val toastLay = LayoutBallonCameraAlbumFirstBinding.inflate(
                        LayoutInflater.from(mContext),
                        viewBinding.root,
                        false
                    )
                    Glide.with(mContext).asBitmap()
                        .apply(RequestOptions().apply {
                            format(DecodeFormat.PREFER_ARGB_8888)

                        })
                        .centerInside()
                        .override(Target.SIZE_ORIGINAL).load(imgUrl)
                        .skipMemoryCache(false)
                        .priority(Priority.IMMEDIATE)
                        .into(object : CustomViewTarget<ImageView, Bitmap>(toastLay.albumFirstImg) {
                            override fun onLoadFailed(errorDrawable: Drawable?) {

                            }

                            @SuppressLint("ResourceType")
                            override fun onResourceReady(
                                resource: Bitmap,
                                transition: Transition<in Bitmap>?,
                            ) {
                                view.post {
                                    toastLay.albumFirstImg.setImageBitmap(resource)
                                    toastLay.albumFirstImg.enableCorner(8.dp2px())
                                    toastLay.albumFirstImgLay.trackData(
                                        page = SpmPageDef.CameraRoute,
                                        element = SpmElementDef.Element_33061,
                                        exposeTime = 0f
                                    )
                                    toastLay.albumFirstImgLay.setOnClickListener {
                                        mActivity.navigationTo(RoutePage.ImageSearch.PAGE_RESULT) {
                                            withString("file_path", imgUrl)
                                        }
                                        dismissBalloon()
                                    }

//                                    ImageUtils.loadImage(mContext, imgUrl, toastLay.albumFirstImg)
                                    balloon = Balloon.Builder(mContext)
                                        .setLayout(toastLay)
                                        .setArrowOrientation(ArrowOrientation.BOTTOM)
                                        .setArrowPositionRules(ArrowPositionRules.ALIGN_BALLOON)
                                        .setArrowColorResource(R.color.sk_gray0)
                                        .setArrowPosition(0.5f)
                                        .setArrowWidth(14)
                                        .setArrowHeight(8)
                                        .setCornerRadius(8f)
                                        .setDismissWhenShowAgain(true)
                                        .setLifecycleOwner(this@CameraTVMActivity)
                                        .setDismissWhenTouchOutside(false)
                                        .build()
                                    balloon?.showAlignTop(view)
                                    downTimer.start(callBack = {
                                    }, onFinish = {
                                        balloon?.dismiss()
                                    })
                                }
                            }

                            override fun onResourceCleared(placeholder: Drawable?) {
                            }
                        })
                }
            })
        }
    }

    private fun dismissBalloon() {
        FlowBus.boolFlowBusNotify(FlowConst.ALBUM_FIRST_POP_DISMISS)
    }
}